package com.eian.boot.common.id.generator.sequence;

import com.eian.boot.common.id.exception.IdGenerationException;
import com.eian.boot.common.id.mapper.IdSegmentMapper;
import com.eian.boot.common.id.model.IdSegmentEntity;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * DB序列号生成器
 * 每次获取下一个序列号（不使用号段缓存）
 *
 * @author alex.meng
 */
@Slf4j
@RequiredArgsConstructor
public class DbSequenceGenerator extends AbstractSequenceGenerator {

    /**
     * 最大重试次数
     */
    private static final int MAX_RETRY = 3;
    private final IdSegmentMapper idSegmentMapper;

    @Override
    public long nextSequence(String bizType) {
        for (int i = 0; i < MAX_RETRY; i++) {
            try {
                // 查询当前配置
                IdSegmentEntity entity = idSegmentMapper.selectByBizType(bizType);
                if (entity == null) {
                    throw new IdGenerationException(
                            "ID序列号生成失败：未找到业务类型[" + bizType + "]的配置，请在id_segment表中初始化该业务类型"
                    );
                }

                // 乐观锁更新（步长为1）
                int affectedRows = idSegmentMapper.updateMaxId(bizType, 1, entity.getVersion());
                if (affectedRows > 0) {
                    // 更新成功，返回新的序列号
                    long nextSeq = entity.getMaxId() + 1;
                    log.debug("获取DB序列号成功：bizType={}, sequence={}", bizType, nextSeq);
                    return nextSeq;
                }

                // 更新失败，说明有并发冲突，重试
                log.debug("DB序列号获取冲突，重试：bizType={}, retry={}", bizType, i + 1);
            } catch (IdGenerationException e) {
                throw e;
            } catch (Exception e) {
                log.error("获取DB序列号异常：bizType={}", bizType, e);
                throw new IdGenerationException("ID序列号生成失败：" + e.getMessage(), e);
            }
        }

        throw new IdGenerationException("ID序列号生成失败：超过最大重试次数，bizType=" + bizType);
    }

    @Override
    public void resetSequence(String bizType) {
        try {
            IdSegmentEntity entity = idSegmentMapper.selectByBizType(bizType);
            if (entity == null) {
                throw new IdGenerationException(
                        "ID序列号重置失败：未找到业务类型[" + bizType + "]的配置"
                );
            }

            // 重置为0
            entity.setMaxId(0L);
            idSegmentMapper.update(entity);
            log.info("DB序列号重置成功：bizType={}", bizType);
        } catch (IdGenerationException e) {
            throw e;
        } catch (Exception e) {
            log.error("重置DB序列号异常：bizType={}", bizType, e);
            throw new IdGenerationException("ID序列号重置失败：" + e.getMessage(), e);
        }
    }
}

